package com.godyao.framework.transaction.annotation;

import cn.hutool.core.util.ClassUtil;
import com.godyao.framework.beans.BeansException;
import com.godyao.framework.beans.factory.BeanFactory;
import com.godyao.framework.beans.factory.BeanFactoryAware;
import com.godyao.framework.beans.factory.ConfigurableListableBeanFactory;
import com.godyao.framework.beans.factory.config.BeanPostProcessor;
import com.godyao.framework.utils.ClassUtils;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 事务处理
 */
public class TxBeanPostProcessor implements BeanFactoryAware, BeanPostProcessor {
    private ConfigurableListableBeanFactory beanFactory;

    @Override
    public Object postPrecessBeanBeforeInitialization(Object bean, String beanName) {
        return bean;
    }

    @Override
    public Object postProcessBeanAfterInitialization(Object bean, String beanName) {
        Class<?> aClass = bean.getClass();
        if (aClass.isAnnotationPresent(Transactional.class)) {
            Transactional transactional = aClass.getAnnotation(Transactional.class);
//            Enhancer enhancer = new Enhancer();
//            enhancer.setSuperclass(bean.getClass());
//            enhancer.setInterfaces(bean.getClass().getInterfaces());
//            enhancer.setCallback(new TxInterceptor(transactional));
            if (ClassUtils.isCglibProxyClass(bean.getClass())) {
                return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), bean.getClass().getSuperclass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        TxManager txManager = beanFactory.getBean("transactionManager", TxManager.class);
                        if (null == txManager) throw new BeansException("请开启事务管理器");
                        Object res = null;
                        try {
                            txManager.beginTransaction();
                            res = method.invoke(bean, args);
                            txManager.commit();
                        } catch (Throwable e) {
                            e.printStackTrace();
                            txManager.rollback();
                        }
                        return res;
                    }
                });
//                return Enhancer.create(bean.getClass().getSuperclass(), new TxInterceptor(transactional));
            }
            return Enhancer.create(bean.getClass(), new TxInterceptor(transactional));
        }
        return bean;
    }



    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
    }

    private class TxInterceptor implements MethodInterceptor {
        private Transactional transactional;

        public TxInterceptor(Transactional transactional) {
            this.transactional = transactional;
        }

        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            TxManager txManager = beanFactory.getBean("transactionManager", TxManager.class);
            if (null == txManager) throw new BeansException("请开启事务管理器");
            Object res = null;
            try {
                txManager.beginTransaction();
                res = method.invoke(o, objects);
                txManager.commit();
            } catch (Throwable e) {
                e.printStackTrace();
                txManager.rollback();
            }
            return res;
        }
    }
}
